/* $RCSFile: CRMPage.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/CRMPage.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:29  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.IO;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Globalization;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

using AddonNice.Core;
using AddonNice.UI;
using AddonNice.UI.WebControls;
using AddonNice.Helpers;
using AddonNice.Security;
using AddonNice.Configuration;
using AddonNice.Design;
using AddonNice.Diagnostics;
using AddonNice.Settings;
using AddonNice.CRMWrapper;

using Trace2    =   System.Diagnostics.Trace;

namespace AddonNice.UI
{
	/// <summary>
	/// This is the Page normally used to load AddonNice Modules
    /// Contains special methods and properties to adapt to MS CRM and modules management
	/// </summary>
	public class CRMPage : ADNPage
    {
        #region common config values
		
        public string CRMAllUsers		            =   LocalizeHelper.Localize("ALL_USERS", "All Users");
		public string DBAllUser		                =   Config.InternallAllUsersRole;
		public string DBAllUser2		            =   Config.InternallAllUsersRole+";";

        public string CRMAdmin                      =   Config.CRMAdminRole;
		public string DBAdmin                       =   Config.InternalAdminRole;
        public string DBAdmin2                      =   Config.InternalAdminRole+";";
        
        #endregion common config values

        #region Properties adapted to crm pages

        private Guid _itemCrmID                     =   Guid.Empty;
		/// <summary>
		/// This is the crm item id that was selected on the module that called the property page
		/// Value come from the request paremeter named ItemCrmID.
		/// If no corresponding request parameter, value is Guid.Empty.
		/// </summary>
		public Guid ItemCrmID
		{
			get
			{
				if (_itemCrmID == Guid.Empty)
				{
					// Determine ItemID if specified
					if (!IsDesignMode)
					{
						string str	        =	Request.Params[StStr.strItemCrmID];
						if ( !string.IsNullOrEmpty(str) )
						{
							try
							{
								_itemCrmID  =   new Guid(str);
							}
							catch(Exception ex)
							{
                                if ( PageTraceSwitch.Sw.TraceError )
								    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMPage ItemCrmID Parse failed for ItemCrmID: '{0}', ex : {1}",str,ex),PageTraceSwitch.Sw.Info);
                                throw;
							}
						}
					}
				}
				return _itemCrmID;
			}	
			set
			{
				_itemCrmID                  =   value;
			}
		}

        #endregion properties adapted to crm pages
        
        #region CRM properties
        
        string _entName = string.Empty;
		/// <summary>
		/// This is the CRM entity attached to this Page via settings parameters
		/// It is the schema name. Empty string if no entity entered.
		/// </summary>
        public string EntityName
        {
            get
            {
                if (string.IsNullOrEmpty(_entName))
                    if (Settings.ContainsKeyNotEmpty(StStr.PageCRMEntityNameSettings))
                        _entName = Settings[StStr.PageCRMEntityNameSettings].Value;
                return _entName;
            }
        }

        Guid _entityID = Guid.Empty;
        /// <summary>
        /// This is the current entity for which we have loaded the iFrame
		/// Value come from the request parameter 'id' sent by the CRM iFrame (dont forget to ask it to send the parameter)
        /// </summary>
        public Guid EntityID
        {
            get
            {
                if ( _entityID == Guid.Empty )
                    _entityID = Wrapper.RequestEntityID;
                return _entityID;
            }
        }

        public static string RequestEntityID
        {
            get
            {
                return CRMWrapperBase.RequestEntityIDStr;
            }
        }
        
        /// <summary>
        /// Crm sends the id query string with {} surounding the guid value, not AddonNice
        /// We use this to differenciate internal and external calls
        /// </summary>
        public bool IsCrmEntityID
        {
            get
            {
                return Wrapper.IsCrmEntityID;
            }
        }

        /// <summary>
        /// When in creation mode we have no entityID, this is the reason why
        /// We add a Crm marker in the iframe url /site/ucrm_1/PageId/xxx.aspx
        /// </summary>
        public bool RequestHasCrmMark
        {
            get
            {
                return Wrapper.RequestHasCrmMark;
            }
        }

        /// <summary>
        /// Get EntityType from parametres sent by CRM to the iFrame Field contaning our Module
        /// </summary>
        public string RequestEntityTypename
        {
            get
            {
                return Wrapper.RequestEntityTypename;
            }
        }


        public string RequestEntityTypeCode
        {
            get
            {
                return Wrapper.RequestEntityTypeCode;
            }
        }
    
        /// <summary>
        /// CRM V4
        /// Get the orgname sent by CRM iFrame as parameter
        /// Organization Name The unique name of the organization. 
        /// </summary>
        public virtual string RequestOrgName
        {
            get
            {
                return Wrapper.RequestOrgName;
            }
        }

        /// <summary>
        /// CRM V4
        /// User LCID sent in request string by CRM from v4, -1 when not initialized or v3
        /// </summary>
        public int CrmUserLCID
        {
            get
            {
                return Wrapper.RequestUserLCID;
            }
        }
        
		/// <summary>
		/// Test if CrmOrg LCID is a child of sent LCID
        /// Because DefLCID in DB is always a base language LCID
		/// </summary>
		public bool IsParentOfCrmOrgLCID(int LCID)
		{
            return Wrapper.IsParentOfCrmOrgLCID(LCID);
        }

        /// <summary>
        /// CRM V4
        /// Org LCID sent in request string by CRM from v4, -1 when not initialized or v3
        /// </summary>
        public int CrmOrgLCID
        {
            get
            {
                return Wrapper.RequestOrgLCID;
            }
        }
        
        /// <summary>
        /// CRM V4
        /// userlcid User Language Code The language code identifier that is used by the current user. 
        /// </summary>
        public virtual string RequestUserLCIDStr
        {
            get
            {
                return Wrapper.RequestUserLCIDStr;
            }
        }

        /// <summary>
        /// CRM V4
        /// orglcid Organization Language Code The language code identifier that represents the base language for the organization. 
        /// </summary>
        public virtual string RequestOrgLCIDStr
        {
            get
            {
                return Wrapper.RequestOrgLCIDStr;
            }
        }
        
        /// <summary>
        /// Is the module called from a CRM iFrame
        /// </summary>
        public virtual bool IsUnderCRM
        {
            get
            {
                return Wrapper.IsUnderCRM;
            }
        }

        public virtual bool IsInEntityCreationMode
        {
            get
            {
                return Wrapper.IsInEntityCreationMode;
            }
        }

        public bool CRMSimulation
        {
            get
            {
                return Wrapper.CRMSimulation;
            }
            set
            {
                Wrapper.CRMSimulation   =   value;
            }
        }

        public bool IsCRMSimulation
        {
            get
            {
                return CRMSimulation;
            }
        }

        /// <summary>
        /// Is the Page attached to a CRM custom entity
        /// </summary>
        public bool IsAttached
        {
            get
            {
                return !string.IsNullOrEmpty(EntityName);
            }
        }

        #endregion CRM properties		

        #region Toolbox for CRM

        /// <summary>
        /// Return the static Wrapper stored in PortalSecurity
        /// </summary>
        public CRMWrapperBase Wrapper
        {
            get
            {
                return AddonNice.Security.PortalSecurity.Wrapper;
            }
        }
		
        /// <summary>
        /// Used to ensure that the wrapper in any DynEntity object is the current one, as they go in cache they need to refresh their wrapper 
        /// </summary>
        protected virtual void ResetWrapper(DynEntity dynEnt)
        {
            CRMWrapperBase  w   =   Wrapper;
            if ( !dynEnt.HasWrapper(w) )
                dynEnt.SetWrapper(w);
        }

        /// <summary>
		/// Execute the request with the CRM logged user, the logged user maynot have enough privileges
		/// </summary>
        protected InternalResponse userExecute(InternalRequest req)
        {
            return internalExecute(req,false);
        }

        /// <summary>
		/// Execute the request with the CRM admin user, to be used when the logged user maynot have enough privileges
		/// </summary>
		protected InternalResponse adminExecute(InternalRequest req)
        {
            return internalExecute(req,true);
        }
		
		private InternalResponse internalExecute(InternalRequest req,bool isAdmin)
        {
			if ( isAdmin )
            	return AddonNice.Security.PortalSecurity.Wrapper.adminExecute(req);
            return AddonNice.Security.PortalSecurity.Wrapper.userExecute(req);
        }

        /// <summary>
        /// Retrieve the data columns specified for the entity corresponding to this guid, using the CRM logged user
		/// Retrieve if exists and if users has privilege to read this data
        /// </summary>
		protected InternalBusinessEntity userRetrieve(string typename, Guid Id, InternalColumnSetBase col)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Retrieve(typename, Id, col, false);
        }

        /// <summary>
        /// Retrieve the data columns specified for the entity corresponding to this guid, using the CRM admin user
		/// Always retrive if exists, beware thtathelogged user may not have rights to see this data
        /// </summary>
		protected InternalBusinessEntity adminRetrieve(string typename, Guid Id, InternalColumnSetBase col)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Retrieve(typename, Id, col, true);
        }
		
        /// <summary>
		/// Retrieve all occurence of entities corresponding to this query and accessible to the logged user
		/// </summary>
        protected InternalBusinessEntityCollection userRetrieveMultiple(InternalQueryBase quer)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.RetrieveMultiple(quer,false);
        }

        /// <summary>
        /// Retrieve all corresponding entities with adminuser, beware that the retrieved datas may not normally be accessible to the logged user
        /// </summary>
		protected InternalBusinessEntityCollection adminRetrieveMultiple(InternalQueryBase quer)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.RetrieveMultiple(quer,true);
        }
 
		/// <summary>
		/// Delete with the logged user, must have corrsponding privilege
		/// </summary>
        protected void userDelete(string typename, Guid Id)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Delete(typename, Id, false);
        }

        /// <summary>
        /// Delete bwith admin user, beware, always delete
        /// </summary>
		protected void adminDelete(string typename, Guid Id)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Delete(typename, Id, true);
        }

		/// <summary>
		/// Update the selected entity with logged user account
		/// </summary>
        protected void userUpdate(InternalBusinessEntity bu)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Update(bu, false);
        }

        /// <summary>
        /// Update with admin user, to be used when the log on user has no rights
		/// The created enty will be marked as modified by the admin
        /// </summary>
		protected void adminUpdate(InternalBusinessEntity bu)
        {
            AddonNice.Security.PortalSecurity.Wrapper.Update(bu,true);
        }

        /// <summary>
        /// Create with admin user, to be used when the log on user has no rights
		/// The created enty will belong to the logged usedr
        /// </summary>
        protected Guid userCreate(InternalBusinessEntity bu)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Create(bu, false);
        }
        /// <summary>
        /// Create with admin user, to be used when the log on user has no rights
		/// The created enty will belong to the admin, must be assigned to some other user later or by workflow
        /// </summary>
 		protected Guid adminCreate(InternalBusinessEntity bu)
        {
            return AddonNice.Security.PortalSecurity.Wrapper.Create(bu, true);
        }

 
        #endregion

        #region Managing Save event from CRM
        
        /// <summary>
        /// Implement the RaisePostBackEvent method from the IPostBackEventHandler interface. 
        /// </summary>
        public override void RaisePostBackEvent(string eventArgument)
        {
            if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage RaisePostBackEvent BEG eventArgument: {0}", eventArgument), PageTraceSwitch.Sw.Info);
            base.RaisePostBackEvent(eventArgument);
            string argument                     =   Server.HtmlDecode(eventArgument);
            string[] args                       =   argument.Split(new char[]{','},StringSplitOptions.RemoveEmptyEntries);
            int count                           =   0;
            foreach (string mid in args)
            {
                try
                {
                    int modId                   =   int.Parse(mid);
                    if (PageTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage RaisePostBackEvent trying mid: {0}", modId), PageTraceSwitch.Sw.Info);
                    if (LoadedModules.ContainsKey(modId))
                    {
                        if (PageTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage RaisePostBackEvent updating mid: {0}", modId), PageTraceSwitch.Sw.Info);
                        PortalModuleControl mod =   LoadedModules[modId];
                        mod.OnADNUpdateModule(EventArgs.Empty);
                        count++;
                    }
                }
                catch (Exception ex)
                {
                    if ( PageTraceSwitch.Sw.TraceError )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMPage RaisePostBackEvent ex : {0}", ex),PageTraceSwitch.Sw.Info);
                    throw;
                }
            }
            if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage RaisePostBackEvent END count: {0}", count), PageTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Build a string argument from the modules in this page, using the modules idscomma separated
        /// </summary>
        protected virtual string GetPostBackArgument()
        {
            if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]CRMPage GetPostBackArgument BEG.",PageTraceSwitch.Sw.Info);
			StringBuilder sb	=	new StringBuilder();

			foreach (ModuleConfiguration ms in portalSettings.ActivePageSettings.Modules)
			{
				sb.AppendFormat("{0},",ms.ModuleID);
			}
            string arg          =   sb.ToString().Trim(new char[]{','});
            arg                 =   Server.HtmlEncode(arg);
            if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage GetPostBackArgument END Argument: {0}", arg), PageTraceSwitch.Sw.Info);
            return arg;
        }
        
        void RegisterSaveFromCrmIFrame()
        {
            if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]CRMPage RegisterSaveFromCrmIFrame BEG.",PageTraceSwitch.Sw.Info);
            Type cs         =   GetType();
            // Check to see if the startup script is already registered.
            string script   =   string.Format("function SaveCRMIframe(){{{0};}}",GetPostbackEventReference(GetPostBackArgument()));
            if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage RegisterSaveFromCrmIFrame script: {0}", script), PageTraceSwitch.Sw.Info);
            RegisterADNClientScriptBlock(cs, "SaveCRMiFrame", script, true);
             if (PageTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]CRMPage RegisterSaveFromCrmIFrame END.",PageTraceSwitch.Sw.Info);
       }
    
        #endregion Managing Save event from CRM

        #region std overrides

        /// <summary>
        /// If exists, installs a portal CRM Theme to use when under CRM
        /// </summary>
        public override string Theme
        {
            get
            {
                if ( !FastLoadPage && IsUnderCRM )
                {
                    string strTm        =   base.Theme;
                    string strTheme     =   portalSettings.DefaultCrmTheme;
                    if (PageTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage Theme GET setting base theme: {0}, CRM theme: {1}",strTm, strTheme), PageTraceSwitch.Sw.Info);
                    if (string.IsNullOrEmpty(strTm) || !strTm.Equals(strTheme) )
                    {
                        if (!string.IsNullOrEmpty(strTheme))
                        {
                            base.Theme  =   strTheme;
                            if (PageTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMPage Theme GET setting theme: {0}", strTheme), PageTraceSwitch.Sw.Info);
                            return strTheme;
                        }
                    }
                }
                return base.Theme;
            }
            set
            {
                base.Theme              =   value;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            if ( !FastLoadPage && IsUnderCRM )
                RegisterSaveFromCrmIFrame();
            base.OnPreRender(e);
        }

        #endregion std overrides
    }
}